/*
 * @Author: Dannycjh 2233879049@qq.com
 * @Date: 2023-04-15 11:57:11
 * @LastEditors: Dannycjh 2233879049@qq.com
 * @LastEditTime: 2023-04-28 14:47:26
 * @FilePath: \cc-game-development-template\assets\game.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
/*
 * @Author: Dannycjh 2233879049@qq.com
 * @Date: 2023-04-15 11:57:11
 * @LastEditors: Dannycjh 2233879049@qq.com
 * @LastEditTime: 2023-04-17 09:04:56
 * @FilePath: \cc-game-development-template\assets\scripts\game.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import { Animation, _decorator, Button, Color, Component, EventTouch, find, Label, macro, math, Node, NodeEventType, Prefab, Quat, resources, Sprite, SpriteFrame, Tween, tween, UITransform, v2, Vec2, Vec3, sys, view, instantiate, random } from 'cc';
import { Constant, EventConst } from '../../../common/Common';
import { App } from '../../../App';
import { LoadMg } from '../../../tools/LoadMg';
import UtilTool from '../../../tools/UtilTool';
import AbstractComponent from '../../../base/AbstractComponent';
import BilliardsGameController from '.././controller/BilliardsGameController';
import { GameModel } from '.././model/GameModel';
import wsTool from '../../../net/ws';
import CommConst from '../../../const/CommConst';
import { Ball } from '../Ball';
import { RigidBodyComponent } from 'cc';
import { RigidBody } from 'cc';
import { GameLayer3 } from './GameLayer3';
import { GameBaseModel } from '../GameBaseModel';
import { showTip, showTipBox } from '../../../tools/PopuUp';
import { EndLayer3 } from './EndLayer3';
import {  CLIENTMSG_SWITCH, MAX_FORCE, MAX_FORCE_BOMB } from '../GameManage';
import { GameMulitLogic } from './GameMulitLogic';
import { GamePlayState } from '../GameBaseLogic';
import { GameMulitMyBall } from './GameMulitMyBall';
import { Role } from '../Role';
import { GameMulitUser } from './GameMulitUser';
import { PD } from '../../../player/PlayerData';
const { ccclass, property } = _decorator;

// 游戏主脚本
@ccclass('GameModel3')
export class GameModel3 extends GameBaseModel {
    @property(Prefab)
    GameMulitMyBallPrefab : Prefab = null;   // 被分配的球layer

    gameLayerCtrl = null
    gameLogic : GameMulitLogic = null

    frameHz = 6     // 帧同步请求频率 (频率越小，同步越频繁)
    frameCount = 0  // 帧数

    frameLogic = 0     // 逻辑帧
    
    protected onLoad(): void {
        super.onLoad();
    }

    protected onEnable(): void {
        super.onEnable();
    }
    
    start() {
        super.start();
        App.WSGameStatus = 2
        this.gameLayerCtrl = this.getGameLayerCtrl(GameLayer3)
        this.gameLogic = new GameMulitLogic()

        this.cueCtrl.showCue(false,this.cueCtrl.ballToCueAngle(this.getWhiteToOneAngle()))

        if (App.Model.gameManage.isReconnectAndGameing() || App.Model.gameManage.isWatchGame) {
            // 断线重连进来的话直接走初始化游戏
            tween(this.node).delay(0.2).call(()=>{
                this.gameLogic.initGame()
            }).start()
        }
        else{
            // 非断线重连的话先展示目标球
            this.showTargetBall()
        }
    }
    
    /**
     * 游戏开始
     */
    gameStart() {
        if (App.Model.gameManage.isReconnectAndGameing()) {
            this.gameLogic.respGameReconnect(App.Model.gameManage.gameReconnectData.playingStatusInfo)
        }
        else if (App.Model.gameManage.isWatchGame) {
            this.gameLogic.respGameReconnect(App.Model.gameManage.gameWatchData.playingStatusInfo)
        }
        else{
            if (CLIENTMSG_SWITCH){
                return
            }

            this.goSystemPlayball()
        }
    }

    /**
     * 执行系统出杆
     */
    goSystemPlayball() {
        if  (!this.node) return;
        
        let gameManage = App.Model.gameManage
        let gameStartData = gameManage.gameStartData

        // 设置上报帧数据的玩家（作用：让第一杆系统杆也会同步帧数据）
        this.gameLogic.uploadAccount = App.Model.gameManage.uploadAccount

        // 力度值 = 基础力度+等级力度
        let force = MAX_FORCE + (gameStartData.dynamics / 15) * (MAX_FORCE_BOMB-MAX_FORCE)

        UtilTool.printLog("系统击球力度值 force",force)
        if (this.node && this.gameLogic.curPlayState == GamePlayState.WAIT_HIT_BALL) {
            this.moveCue(this.getWhiteToOneAngle(), force)
        }
    }

    /**
     * 展示被分配的球
     */
    showTargetBall() {
        let node = instantiate(this.GameMulitMyBallPrefab)
        this.viewNode.addChild(node)
        node.getComponent(GameMulitMyBall).setData(()=>{
            // 展示完分配的球后开始游戏
            this.gameLogic.initGame()
        })

    }

    // 收到球进洞事件
    ballInRoleEvent(ballNumber : number, ballNode : Node, role : Role) {
        if  (!this.node) return;
        this.gameLogic.ballInRoleEvent(ballNumber, ballNode, role)
    }

    // 收到开始击球事件
    startHitBallEvent(event) {
        UtilTool.printLog("GameModel1 start hit ball")
        this.gameLogic.startHitBallEvent(event)
        this.frameCount = this.frameHz
    }
    
    // 收到白球碰撞球事件
    whiteBallContactEvent(ballNumber : number) {
        UtilTool.printLog("GameModel1 收到白球碰撞球事件")
        this.isOpenBallStatus = false
        if(!this.gameLogic) {
            return // 游戏开始时会有碰球的情况
        }

        this.gameLogic.whiteBallContactEvent(ballNumber)

    }

    // 收到摆球结束事件
    whiteBallPosEndEvent(whiteBallPos) {
        UtilTool.printLog("GameModel1 white ball pos end", whiteBallPos)
        this.gameLogic.whiteBallPosEndEvent(whiteBallPos)
    }

    // 收到击球结束事件
    hitBallEndEvent() {
        this.gameLogic.hitBallEndEvent()
        
    }

    update(deltaTime: number) {
        super.update(deltaTime)

        this.frameCount = this.frameCount + 1

        // 当前玩家是自己，并且是在击球的状态则上报帧同步
        if (this.frameCount >= this.frameHz) {
            if (CLIENTMSG_SWITCH){
                if (this.gameLogic.curPlayState==GamePlayState.WAIT_HIT_BALL) {
                    this.gameLogic.curPlayState = GamePlayState.HIT_BALL
                }
                
                if (this.gameLogic.curPlayState==GamePlayState.HIT_BALL) {
                    let frameDataOne = App.Model.gameManage.frameData[this.frameLogic]
                    if (frameDataOne) {
                        this.gameLogic.respFrameData({"allBallInfo":frameDataOne})
                        this.frameLogic++
                        this.frameCount = 0
                    }
                }

                return
            }

            // if (this.gameLogic.curPlayUser && this.gameLogic.curPlayUser.mine && this.gameLogic.curPlayState==GamePlayState.HIT_BALL) { 
            if (this.gameLogic.curPlayUser && this.gameLogic.isMineAccount(this.gameLogic.uploadAccount) && this.gameLogic.curPlayState==GamePlayState.HIT_BALL) {
                this.frameCount = 0
                this.reqFrameDataMsg()
            }
        }
        
    }

    /////////////////////////////////////////////////////////////// 请求消息 ////////////////////////////////////////////////////////////////////
    /**
     * 请求认输
     */
    reqGiveUpMsg(cb) {
        let controller = this.controller as BilliardsGameController
        controller.reqGiveUpMsg(cb)
    }

    /**
     * 请求客户端开球
     */
    reqOpenBallMsg(allBallInfo) {
        let controller = this.controller as BilliardsGameController
        controller.reqOpenBallMsg(allBallInfo)
    }

    /**
     * 请求调整球杆角度
     */
    reqChangeCueMsg(cueAngle) {
        let controller = this.controller as BilliardsGameController
        controller.reqChangeCueMsg(cueAngle)
    }

    /**
     * 请求玩家击球
     * @param cueAngle 球的角度
     * @param dynamics 力度
     */
    reqHitballMsg(angle, dynamics) {
        let controller = this.controller as BilliardsGameController
        controller.reqHitballMsg(angle, dynamics)
    }

    /**
     * 请求球桌运动结束，上报击球结果
     * @param motherBall 0:母球正常打球 1:母球没有击中任何球 2:母球先击中别家球 3:母球进洞了
     * @param enterBall 进洞的球号
     * @param allBallInfo 各个球的信息
     */
    reqHitballEndMsg(motherBall, enterBall, allBallInfo, wheel) {
        if (this.gameLogic.curPlayState == GamePlayState.GAME_END) {
            return
        }
        
        let controller = this.controller as BilliardsGameController
        controller.reqHitballEndMsg(motherBall, enterBall, allBallInfo, wheel)
    }

    /**
     * 请求上报重新摆球的结果
     */
    reqPosBallResoultMsg(allBallInfo) {
        let controller = this.controller as BilliardsGameController
        controller.reqPosBallResoultMsg(allBallInfo)
    }

    /** 
     * 请求上报帧数据
     */
    reqFrameDataMsg() {
        let controller = this.controller as BilliardsGameController
        let allBallInfo = this.gameLogic.getAllBallPos()
        controller.reqFrameDataMsg(allBallInfo)
    }

    /**
     * 请求退出观战
     */
    reqQuitWatchMsg() {
        let controller = this.controller as BilliardsGameController
        controller.reqQuitWatchMsg()
    }

    /**
     * 请求查询玩家剩余台球
     */
    reqUsersBallListMsg(cb) {
        let controller = this.controller as BilliardsGameController
        let roomId = App.Model.gameManage.roomId
        let roomType = App.Model.gameManage.gameStartData.roomType
        controller.reqUsersBallListMsg(roomId, roomType, cb)
    }
    
    
    /////////////////////////////////////////////////////////////// 请求消息 ////////////////////////////////////////////////////////////////////


    /**
     * 游戏结束
     */
    public gameOver(data) {
        resources.load('prefabs/game/layer3/GameEndLayer3',Prefab,(err,prefabs) =>{
            let layerNode = instantiate(prefabs);
            this.viewNode.addChild(layerNode);

            if (PD.user.addressUrl == data.winPlayerAccount) {
                layerNode.getComponent(EndLayer3).showView(data, 1)
            }
            else {
                layerNode.getComponent(EndLayer3).showView(data, 2)
            }
        })
    }

    onDestroy() {
        App.WSGameStatus = 0
    }

}

